﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Xml.Linq;
using Image = System.Windows.Controls.Image;
using System.Collections;

namespace BanditGame
{
	public partial class MainPage : UserControl
	{
		#region variables
		/// <summary>
		/// Current level number
		/// </summary>
		private int _currentLevelNumber = 0;

		/// <summary>
		/// Score of the current player
		/// </summary>
		private int _score = 0;

		/// <summary>
		/// Life of the current player
		/// </summary>
		private int _life = 0;

		/// <summary>
		/// Definition of current level
		/// </summary>
		private Level _currentLevel = new Level();

		/// <summary>
		/// Last time for pressed keys
		/// </summary>
		private DateTime _lastExecution = DateTime.MinValue;

		/// <summary>
		/// Player
		/// </summary>
		private Bandit _myBandit = new Bandit();
		
		/// <summary>
		/// Image presenting player on gamefield
		/// </summary>
		private Image _myBanditImage = new Image() { Source = new BitmapImage(new Uri("Images/Bandit.png", UriKind.Relative)), Width = Defaults.CellSizeInPixel };
		 
		 /// <summary>
		 /// Game field for level 
		 /// </summary>
		private Canvas GameField = new Canvas();

		/// <summary>
		/// This canvas is just black background as game fiel border (easier dynamic change that Border..)
		/// </summary>
		private Canvas GameFieldBorder = new Canvas();

		#endregion


		/// <summary>
		/// TEST GUARDIAN
		/// </summary>
		//private Guardian _testGuardian = new Guardian();
		IList<Guardian> lGuardians = new List<Guardian>();
		IList<Image> lGuardiansImage = new List<Image>();

		/// <summary>
		/// Mainpage method
		/// </summary>
		public MainPage()
		{
			InitializeComponent();
		}

		/// <summary>
		/// Timer for levelTime
		/// </summary>
		public void StartTimer()
		{
			System.Windows.Threading.DispatcherTimer myDispatcherTimer = new System.Windows.Threading.DispatcherTimer();
			myDispatcherTimer.Interval = new TimeSpan(0, 0, 1); // 1 second 
			myDispatcherTimer.Tick += new EventHandler(Each_Tick);
			myDispatcherTimer.Start();
		}
		
		/// <summary>
		///  Tick method for levelTimer
		/// </summary>
		public void Each_Tick(object o, EventArgs sender)
		{
			myTextBlock.Text = String.Format("{0:0,0}", (_currentLevel.levelTime / 60)) + ":" + String.Format("{0:0,0}", (_currentLevel.levelTime % 60));
			_currentLevel.levelTime--;
		}

		public void newGame()
		{

		}
		
		/// <summary>
		/// Handling KeyDown events
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void UserControl_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
		{
			if ((DateTime.Now - _lastExecution).TotalMilliseconds > Defaults.KeyDownDelayForBandit)
			{
				if (e.Key.Equals(Key.Up))
				{
					_myBandit.moveUp();
					if (!_myBandit.CheckForCollision(_currentLevel))
					{
						_myBandit.updatePosition();
					}
					ImageUpdatePosition(_myBanditImage, _myBandit.PositionX, _myBandit.PositionY);
					
				}
				if (e.Key.Equals(Key.Down))
				{
					_myBandit.moveDown();
					if (!_myBandit.CheckForCollision(_currentLevel))
					{
						_myBandit.updatePosition();
					}
					ImageUpdatePosition(_myBanditImage, _myBandit.PositionX, _myBandit.PositionY);
				}
				if (e.Key.Equals(Key.Left))
				{
					_myBandit.moveLeft();
					if (!_myBandit.CheckForCollision(_currentLevel))
					{
						_myBandit.updatePosition();
					}
					ImageUpdatePosition(_myBanditImage, _myBandit.PositionX, _myBandit.PositionY);
				}
				if (e.Key.Equals(Key.Right))
				{
					_myBandit.moveRight();
					if (!_myBandit.CheckForCollision(_currentLevel))
					{
						_myBandit.updatePosition();
					}
					ImageUpdatePosition(_myBanditImage, _myBandit.PositionX, _myBandit.PositionY);
				}
				//test key
				if (e.Key.Equals(Key.A))
				{

				}
				_lastExecution = DateTime.Now;
			}
		}

		public void callCheckVisibility()
		{
			Boolean visibility = false;
			foreach (var guardian in lGuardians)
			{
				if (guardian.checkVisibility(_myBandit.PositionX, _myBandit.PositionY, _currentLevel) && !visibility)
					visibility = true;    
			}
			if (visibility)
			{
				myTextCollision.Text = ("Strazce te vidi!");
			}
			else
					myTextCollision.Text = ("..");
		}

		/// <summary>
		/// Updates position of image objects
		/// </summary>
		/// <param name="image"></param>
		/// <param name="x"></param>
		/// <param name="y"></param>
		public void ImageUpdatePosition(Image image, int x, int y)
		{
			//check if visibility
			callCheckVisibility();

			image.SetValue(Canvas.TopProperty, GridToPixelConverter.GetPixelFromGrid(y));
			image.SetValue(Canvas.LeftProperty, GridToPixelConverter.GetPixelFromGrid(x));
		}

		/// <summary>
		/// This method manage Gamefiel change on new level
		/// </summary>
		public void ShowNewLevel()
		{
			_currentLevel = LoadCurrentLevelFromXML(); //***************

			//removing old level canvas
			GameField.Children.Remove(_myBanditImage);
			LayoutRootGrid.Children.Remove(GameField);
			LayoutRootGrid.Children.Remove(GameFieldBorder);
			GameField = new Canvas();
			GameFieldBorder = new Canvas();

			//loading new level canvas
			GameField.Width = (_currentLevel.SizeX + 1) * Defaults.CellSizeInPixel;
			GameField.Height = (_currentLevel.SizeY + 1) * Defaults.CellSizeInPixel;
			GameFieldBorder.Width = (_currentLevel.SizeX + 1) * Defaults.CellSizeInPixel + 10;
			GameFieldBorder.Height = (_currentLevel.SizeY + 1) * Defaults.CellSizeInPixel + 10;

			GameFieldBorder.Background = new SolidColorBrush(Colors.Black);

			Grid.SetColumn(GameFieldBorder, 1);
			Grid.SetRow(GameFieldBorder, 1);
			Grid.SetColumn(GameField, 1);
			Grid.SetRow(GameField, 1);

			LayoutRootGrid.Children.Add(GameFieldBorder);
			LayoutRootGrid.Children.Add(GameField);

			DrawLevel();
			
			_myBandit.PositionX = _currentLevel.StartingX;
			_myBandit.PositionY = _currentLevel.StartingY;

			//Set bandit starting position
			_myBanditImage.SetValue(Canvas.TopProperty, GridToPixelConverter.GetPixelFromGrid(_myBandit.PositionY));
			_myBanditImage.SetValue(Canvas.LeftProperty, GridToPixelConverter.GetPixelFromGrid(_myBandit.PositionX));
			GameField.Children.Add(_myBanditImage);

			StartTimer();
		}

		/// <summary>
		/// This method is drawing whole Gamefield, cell by cell
		/// </summary>
		public void DrawLevel()
		{
			//'#' Wall 
			//' ' Empty floor cell
			//'?' Question
			//'@' Finnish
			//'!'  Guardian
			//'$' 
			//'.' 
			

			foreach (var cell in _currentLevel.CellList)
			{
				switch (cell.CellType)
				{
					//CELLS
					case '#':   // Walls
						Image WallPic = new Image() { Source = new BitmapImage(new Uri("Images/Wall.png", UriKind.Relative)), Width = Defaults.CellSizeInPixel };
						WallPic.SetValue(Canvas.TopProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionY));
						WallPic.SetValue(Canvas.LeftProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionX));
						GameField.Children.Add(WallPic);
						break;
					case ' ':   // Empty cell
						Image EmptyPic = new Image() { Source = new BitmapImage(new Uri("Images/Cell.png", UriKind.Relative)), Width = Defaults.CellSizeInPixel };
						EmptyPic.SetValue(Canvas.TopProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionY));
						EmptyPic.SetValue(Canvas.LeftProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionX));
						GameField.Children.Add(EmptyPic);
						break;
					case '?':   // Question
						Image EmptyPic2 = new Image() { Source = new BitmapImage(new Uri("Images/Cell.png", UriKind.Relative)), Width = Defaults.CellSizeInPixel };
						EmptyPic2.SetValue(Canvas.TopProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionY));
						EmptyPic2.SetValue(Canvas.LeftProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionX));
						GameField.Children.Add(EmptyPic2);
						Image QuestionPic = new Image() { Source = new BitmapImage(new Uri("Images/Question.png", UriKind.Relative)), Width = Defaults.CellSizeInPixel };
						QuestionPic.SetValue(Canvas.TopProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionY));
						QuestionPic.SetValue(Canvas.LeftProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionX));
						GameField.Children.Add(QuestionPic);
						break;
					case '!':   // Guardian
						addGuardian(cell.PositionX, cell.PositionY);
						/*_testGuardian.PositionX = cell.PositionX;
						_testGuardian.PositionY = cell.PositionY;

						Image GuardianPic = new Image() { Source = new BitmapImage(new Uri("Images/Guardian.png", UriKind.Relative)), Width = Defaults.CellSizeInPixel };
						GuardianPic.SetValue(Canvas.TopProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionY));
						GuardianPic.SetValue(Canvas.LeftProperty, GridToPixelConverter.GetPixelFromGrid(cell.PositionX));
						GameField.Children.Add(GuardianPic);*/
						break;
				}
			}
		}

		public void addGuardian(int X, int Y)
		{
			
			//_Guardian.PositionX = X;
			//_Guardian.PositionY = Y;
			lGuardians.Add(new Guardian(X, Y));
			lGuardiansImage.Add(new Image() { Source = new BitmapImage(new Uri("Images/Guardian.png", UriKind.Relative)), Width = Defaults.CellSizeInPixel });
			//Image GuardianPic = new Image() { Source = new BitmapImage(new Uri("Images/Guardian.png", UriKind.Relative)), Width = Defaults.CellSizeInPixel };
			lGuardiansImage.Last().SetValue(Canvas.TopProperty, GridToPixelConverter.GetPixelFromGrid(Y));
			lGuardiansImage.Last().SetValue(Canvas.LeftProperty, GridToPixelConverter.GetPixelFromGrid(X));
			GameField.Children.Add(lGuardiansImage.Last());
		}

		//TODO - osetrit neexistujici level
		/// <summary>
		/// Loading current level
		/// </summary>
		/// <returns>CurrentLevel</returns>
		public Level LoadCurrentLevelFromXML()
		{
			Level returnLevel = new Level();
			
			try
			{
				XDocument xdoc = XDocument.Load(string.Format("Levels/{0}.xml", _currentLevelNumber.ToString("0000")));

				if (xdoc != null)
				{
					var xmlLevel =
						(from l in xdoc.Descendants("Level")
						 //where (int)l.Attribute("LevelNumber") == actualLevelNumber
						 select new Level()
									{
										LevelNumber = Convert.ToInt32(l.Attribute("levelNumber").Value),
										StartingX = Convert.ToInt32(l.Attribute("startingX").Value),
										StartingY = Convert.ToInt32(l.Attribute("startingY").Value),
										SizeX = Convert.ToInt32(l.Attribute("sizeX").Value),
										SizeY = Convert.ToInt32(l.Attribute("sizeY").Value),
										levelTime = Convert.ToInt32(l.Attribute("levelTime").Value),
										CellList = (from c in l.Descendants("Cell")
													select new Cell
															   {
																   CellType =
																	   Convert.ToChar(c.Attribute("CellType").Value),
																   PositionX =
																	   Convert.ToInt32(c.Attribute("PositionX").Value),
																   PositionY =
																	   Convert.ToInt32(c.Attribute("PositionY").Value)
															   }).ToList()
									}
						).FirstOrDefault();
					returnLevel = xmlLevel;
				}
			}
			catch (Exception e)
			{
				//TODO ERROR LEVEL NEEXISTUJE NEBO JE SPATNE DEFINOVAN
			}
			return returnLevel;
		}


		#region Test Buttons
		
		private void Level1Button_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			if (_currentLevelNumber != 1)
			{
				_currentLevelNumber = 1;
				ShowNewLevel();
			}			
		}

		private void Level2Button_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			if (_currentLevelNumber != 2)
			{
				_currentLevelNumber = 2;
				ShowNewLevel();
			}
		}

		private void Level3Button_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			if (_currentLevelNumber != 3)
			{
				_currentLevelNumber = 3;
				ShowNewLevel();
			}
		}

		private void Level4Button_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			if (_currentLevelNumber != 4)
			{
				_currentLevelNumber = 4;
				ShowNewLevel();
			}
		}
	
		#endregion
	}
}
